package apis;

import java.util.Date;
import java.util.EnumSet;
import java.util.List;

import models.SmartsheetToken;
import models.User;

import com.smartsheet.api.AttachmentResources;
import com.smartsheet.api.RowResources;
import com.smartsheet.api.ShareResources;
import com.smartsheet.api.SheetResources;
import com.smartsheet.api.Smartsheet;
import com.smartsheet.api.SmartsheetBuilder;
import com.smartsheet.api.SmartsheetException;
import com.smartsheet.api.internal.ShareResourcesImpl;
import com.smartsheet.api.internal.SmartsheetImpl;
import com.smartsheet.api.models.Attachment;
import com.smartsheet.api.models.ObjectInclusion;
import com.smartsheet.api.models.Share;
import com.smartsheet.api.models.Sheet;
import com.smartsheet.api.oauth.OAuthFlow;
import com.smartsheet.api.oauth.Token;

import controllers.OAuthController;

public class SmartsheetApi {

    /**
     * Get Smartsheet object of logged in user
     * @param user logged in user
     * @return Smartsheet object
     * @throws Exception
     */
    public static Smartsheet getSmartsheet(User user) throws Exception {
    	SmartsheetToken ssToken = user.token;
    	// handle refresh
    	checkTokenExpire(ssToken);
		Smartsheet smartsheet = new SmartsheetBuilder().setAccessToken(ssToken.accessToken).build();
		return smartsheet;
    }
    
    /**
     * Get sheet list of logged user
     * @param smartsheet Smartsheet interface
     * @return list of Sheet
     * @throws SmartsheetException
     */
    public static List<Sheet> getSheets(Smartsheet smartsheet) throws SmartsheetException {
    	return smartsheet.sheets().listSheets();
    }
    
    /**
     * get a sheet
     * @param smartsheet Smartsheet interface
     * @param sheetId sheet id to fetch
     * @return the fetched Sheet object
     * @throws SmartsheetException
     */
    public static Sheet getSheet(Smartsheet smartsheet, Long sheetId) throws SmartsheetException {
    	EnumSet<ObjectInclusion> enumSet = EnumSet.of(ObjectInclusion.COLUMNS);
    	enumSet.add(ObjectInclusion.DATA);
    	
    	SheetResources sheetResources = smartsheet.sheets();
//    	RowResources rowResources = smartsheet.rows();
    	return sheetResources.getSheet(sheetId, enumSet);
    }
    
    /**
     * 
     * @param smartsheet Smartsheet interface
     * @param rowId parent row id of attachment
     * @param attachmentId attachment id to fetch
     * @return the fetched Attachment object
     * @throws SmartsheetException
     */
    public static Attachment getAttachment(Smartsheet smartsheet, Long rowId, Long attachmentId) throws SmartsheetException {
		// user AttachmentResources to get attachment url 
		AttachmentResources attachmentResources = smartsheet.attachments();
		Attachment attachment = attachmentResources.getAttachment(attachmentId);
		// attachment.getParentId() returns null, set it manually
		attachment.setParentId(rowId);
		return attachment;
    }
    
	/**
	 *  Find Smartsheet collaborators, which is share.
	 * @param smartsheet Smartsheet interface
	 * @param sheetId sheet id to get shares from
	 * @return list of Share
	 * @throws SmartsheetException
	 */
    public static List<Share> getSheetShares(Smartsheet smartsheet, Long sheetId) throws SmartsheetException {
    	// Smartsheet does not have api for ShareResources, so now use impl class directly
		ShareResources shareResources = new ShareResourcesImpl((SmartsheetImpl)smartsheet, "sheet");
		return shareResources.listShares(sheetId);
    }
    /**
     * Check whether Smartsheet token expired or not. If expired, refreshes the token and save the refreshed token
     * to database.
     * @param ssToken Smartsheet token to check
     * @throws Exception
     */
    private static void checkTokenExpire(SmartsheetToken ssToken) throws Exception {
    	if (ssToken.expiresDate.after(new Date())) {
    		// if expired, refresh the token
    		OAuthFlow oauthFlow = OAuthController.getAuthFlow();
    		Token token = SmartsheetToken.getTokenFromSmartsheetToken(ssToken);
    		Token refreshedToken = oauthFlow.refreshToken(token);
    		// update SmartsheetToken and save
    		ssToken.updateFromToken(refreshedToken);
    		SmartsheetToken.saveOrUpdate(ssToken);
    	}
    }
}
